package com.hqyj.javaSpringBoot.modules.test.service.impl;

import com.hqyj.javaSpringBoot.modules.common.entity.Result;
import com.hqyj.javaSpringBoot.modules.common.entity.SearchBean;
import com.hqyj.javaSpringBoot.modules.test.dao.StudentRepository;
import com.hqyj.javaSpringBoot.modules.test.entity.Student;
import com.hqyj.javaSpringBoot.modules.test.service.StudentService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

@Service
public class StudentServiceImpl implements StudentService {
    @Autowired
    private StudentRepository studentRepository;

    @Autowired
    private EntityManager entityManager;

    /*@Override
    @Transactional
    public Result<Student> insertStudent(Student student) {
        //保存且刷新
        studentRepository.saveAndFlush(student);
        return new Result<Student>(Result.ResultCode.SUCCESS.code,
                "Insert Success.", student);
    }*/

    @Override
    @Transactional
    public Result<Student> editStudent(Student student) {
        //保存且刷新
//        studentRepository.saveAndFlush(student);
        studentRepository.insertStudent(student);
        return new Result<Student>(Result.ResultCode.SUCCESS.code,
                "Edit Success.", student);
    }

    @Override
    @Transactional
    public Result<Object> deleteStudent(int id) {
        studentRepository.deleteById(id);
        return new Result<Object>(Result.ResultCode.SUCCESS.code,
                "Delete Success.");
    }

    @Override
    public Student getStudentById(int id) {
//        return studentRepository.getById(id);
//        return studentRepository.getStudentById(id);
        return studentRepository.getStudentByIdForSql(id);
    }

    @Override
    public List<Student> getStudents() {
        return Optional
                .ofNullable(studentRepository.findAll())
                .orElse(Collections.emptyList());
    }

    @Override
    public Student getStudentByNameAndEmail(String name, String email) {
        return studentRepository.findFirstByNameAndEmail(name, email);
    }

    @Override
    public Page<Student> getStudentsBySearchBean(SearchBean searchBean) {
        searchBean.initSearchBean();
        //<S extends T> Page<S> findAll(Example<S> var1, Pageable var2);
        Sort.Direction direction = StringUtils.isBlank(searchBean.getDirection()) ||
                searchBean.getDirection().toLowerCase().equals("asc") ?
                Sort.Direction.ASC : Sort.Direction.DESC;
        Sort sort = Sort.by(direction, searchBean.getOrderBy()); //排序对象
        //     起始页从0开始，则需要 -1
        Pageable pageable = PageRequest.of(
                searchBean.getCurrentPage() - 1,
                searchBean.getPageSize(),
                sort);
        Student student = new Student();
        student.setName(searchBean.getKeyword());
        student.setEmail(searchBean.getKeyword());
        //  matchingAny 相当于or连接查询条件，matching相当于and连接查询条件（matchingAll同）
        ExampleMatcher matcher = ExampleMatcher
                .matchingAny()
                .withMatcher("name", match -> match.contains())
                .withMatcher("email", match -> match.contains());
        Example example = Example.of(student, matcher);

        return studentRepository.findAll(example, pageable);
    }

    /**
     * 批量插入操作
     *      方式1：调用父接口已经实现的接口saveAllAndFlush()方法
     *      方式2：引入EntityManager，使用persist()方法对每一个数据进行实例化
     *          先全部实例化后，再一次性同步到数据库中，效率高
     *          + 最后要加上事务才能操作成功
     */
    @Override
    @Transactional
    public Result<Object> insertStudents(List<Student> students) {
//        studentRepository.saveAllAndFlush(students);
        students.stream().forEach(item -> {
            entityManager.persist(item);
        });
        entityManager.flush();
        entityManager.clear();
        return new Result<Object>(Result.ResultCode.SUCCESS.code,
                "Insert Success.");
    }
}
